#pragma once
#include <thread>
#include <mutex>
namespace wzh
{
	template <class T>
	class shared_ptr
	{
	public:
		shared_ptr(T* ptr = nullptr) 
			: _ptr(ptr)
			, _preCount(new int(1))
			, _mtx(new std::mutex)
		{}

		shared_ptr(shared_ptr<T>& sp)
			: _ptr(sp._ptr)
			, _preCount(sp._preCount)
			, _mtx(sp._mtx)
		{
			addCount();
		}

		void addCount()
		{
			_mtx->lock();
			++(*_preCount);
			_mtx->unlock();
		}

		void relCount()
		{
			_mtx->lock();
			bool flag = false;
			if (--(*_preCount) == 0 && _ptr)
			{
				delete _ptr;
				delete _preCount;
				flag = true;
			}
			_mtx->unlock();
			if (flag) delete _mtx;
		}

		~shared_ptr()
		{
			relCount();
		}

		T& operator*()
		{
			return *_ptr;
		}

		T* operator->()
		{
			return _ptr;
		}

		shared_ptr<T>& operator=(shared_ptr<T>& sp)
		{
			if (this != &sp)
			{
				relCount();
				_ptr = sp._ptr;
				_preCount = sp._preCount;
				_mtx = sp._mtx;
				addCount();
			}
			return *this;
		}

		T* getPtr()
		{
			return _ptr;
		}

	private:
		T* _ptr;
		int* _preCount;
		std::mutex* _mtx;
	};
}